package org.cable.shop.component;

import com.alibaba.fastjson.JSONObject;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.Date;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.util.EntityUtils;
import org.cable.common.util.CommonUtil;
import org.cable.shop.config.PayBeanConfig;
import org.cable.shop.config.WechatPayApi;
import org.cable.shop.config.WechatPayConfig;
import org.cable.shop.vo.PayInfoVO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Service;

/**
 * 微信支付策略
 *
 * @author hsj
 * @date 2023/11/22 11:28
 */
@Service
@Slf4j
public class WechatPayStrategy implements PayStrategy {

	@Autowired
	private WechatPayConfig payConfig;

	@Autowired
	private CloseableHttpClient wechatPayClient;

	@Override
	public String unifiedOrder(PayInfoVO payInfoVO) {

		//全网所有课程都有 过期时间 RFC 3339格式
		SimpleDateFormat sdf = new
			SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssXXX");
		//⽀付订单过期时间
		String timeExpire = sdf.format(new
			                               Date(System.currentTimeMillis() +
				                                    payInfoVO.getOrderPayTimeoutMills()));

		String outTradeNo = payInfoVO.getOutTradeNo();
		JSONObject payObj = new JSONObject();
		payObj.put("mchid", payConfig.getMchId());
		payObj.put("out_trade_no", outTradeNo);
		payObj.put("appid", payConfig.getWxPayAppid());
		payObj.put("description", payInfoVO.getTitle());
		payObj.put("notify_url", payConfig.getCallbackUrl());

		//订单总金额，单位为分。
		JSONObject amountObj = new JSONObject();
		//数据库中double类型11.1元存储
		int amount = payInfoVO.getPayFee().multiply(BigDecimal.valueOf(100)).intValue();
		amountObj.put("total", amount);
		amountObj.put("currency", "CNY");

		payObj.put("amount", amountObj);
		//附属参数，可以用在回调
		payObj.put("attach", "{\"accountNo\":" + payInfoVO.getAccountNo() + "}");
		payObj.put("time_expire", timeExpire);

		String body = payObj.toJSONString();

		log.info("请求参数:{}", body);

		StringEntity entity = new StringEntity(body, "utf-8");
		entity.setContentType("application/json");

		HttpPost httpPost = new HttpPost(WechatPayApi.NATIVE_ORDER);
		httpPost.setHeader("Accept", "application/json");
		httpPost.setEntity(entity);
		String result = "";
		try (CloseableHttpResponse response = wechatPayClient.execute(httpPost)) {

			//响应码
			int statusCode = response.getStatusLine().getStatusCode();
			//响应体
			String responseStr = EntityUtils.toString(response.getEntity());

			log.info("下单响应码:{},响应体:{}", statusCode, responseStr);
			if (statusCode == HttpStatus.OK.value()) {
				JSONObject jsonObject = JSONObject.parseObject(responseStr);
				if (jsonObject.containsKey("code_url")) {
					result = jsonObject.getString("code_url");
				}
			} else {
				log.error("下单失败:{},响应体:{}", statusCode, responseStr);
			}

		} catch (Exception e) {
			log.error("微信支付响应异常:{}", e);
		}
		return result;
	}

	@Override
	public String refund(PayInfoVO payInfoVO) {
		return PayStrategy.super.refund(payInfoVO);
	}

	@Override
	public String queryPayStatus(PayInfoVO payInfoVO) {
		String outTradeNo = payInfoVO.getOutTradeNo();
		String url = String.format(WechatPayApi.NATIVE_QUERY, outTradeNo, payConfig.getMchId());
		HttpGet httpGet = new HttpGet(url);
		httpGet.setHeader("Accept", "application/json");
		String result = "";
		try (CloseableHttpResponse response = wechatPayClient.execute(httpGet)) {
			//响应码
			int statusCode = response.getStatusLine().getStatusCode();
			//响应体
			String responseStr = EntityUtils.toString(response.getEntity());

			log.info("查询响应码:{},响应体:{}", statusCode, responseStr);
			if (statusCode == HttpStatus.OK.value()) {
				JSONObject jsonObject = JSONObject.parseObject(responseStr);
				if (jsonObject.containsKey("trade_state")) {
					result = jsonObject.getString("trade_state");
				}
			} else {
				log.error("查询支付相应失败:{},响应体:{}", statusCode, responseStr);
			}

		} catch (Exception e) {

			log.error("微信查询支付响应异常");
		}
		return result;
	}

	@Override
	public String closeOrder(PayInfoVO payInfoVO) {
		String outTradeNo = payInfoVO.getOutTradeNo();
		JSONObject payObj = new JSONObject();
		payObj.put("mchid", payConfig.getMchId());

		String body = payObj.toJSONString();

		log.info("请求参数:{}", body);
		//将请求参数设置到请求对象中
		StringEntity entity = new StringEntity(body, "utf-8");
		entity.setContentType("application/json");

		String url = String.format(WechatPayApi.NATIVE_CLOSE_ORDER, outTradeNo);
		HttpPost httpPost = new HttpPost(url);
		httpPost.setHeader("Accept", "application/json");
		httpPost.setEntity(entity);
		String result = "";
		try (CloseableHttpResponse response = wechatPayClient.execute(httpPost)) {
			//响应码
			int statusCode = response.getStatusLine().getStatusCode();
			log.info("关闭订单响应码:{},无响应体", statusCode);
            if (statusCode==HttpStatus.NO_CONTENT.value()){
				result = "CLOSE_SUCCESS";
            }
		} catch (Exception e) {
			log.error("关闭订单相应异常");
		}
		return result;
	}

}
